﻿//***********************************************************************
// Assembly         : IGolovkine.AoA.Core
// Author           : Ilia
// Created          : 06-11-2011
//
// Last Modified By : Ilia
// Last Modified On : 06-11-2011
// Description      : 
//
// Copyright        : (c) Microsoft. All rights reserved.
//***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using IGolovkine.AoA.BinarySerialization;
using System.Globalization;

namespace IGolovkine.AoA
{
    [Serializable]
    public struct CorrelationId : IEquatable<CorrelationId>, ISlimBinarySerializable
    {
        private static int _idRegister = 0;
        private Int32 _id;

        private CorrelationId(bool initialised)
        {
            if (initialised)
            {
                _id = Interlocked.Increment(ref _idRegister);
            }
            else
            {
                _id = 0;
            }
        }

        private CorrelationId(ISlimBinaryReader reader)
        {
            _id = reader.ReadInt32();
        }

        public int Id
        {
            get { return _id; }
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentCulture, "CorrelationId: {0}", _id);
        }

        /// <summary>
        /// Nexts this instance.
        /// </summary>
        /// <returns></returns>
        public static CorrelationId Next()
        {
            return new CorrelationId(true);
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        public bool Equals(CorrelationId other)
        {
            if (_id == 0 || other._id == 0)
            {
                throw new ArgumentException("Cannot compare to an uninitialized instance");
            }
            return _id == other._id;
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            return this.Equals((CorrelationId)obj);
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return _id.GetHashCode();
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="id1">The id1.</param>
        /// <param name="id2">The id2.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static bool operator ==(CorrelationId id1, CorrelationId id2)
        {
            return object.Equals(id1, id2);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="id1">The id1.</param>
        /// <param name="id2">The id2.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static bool operator !=(CorrelationId id1, CorrelationId id2)
        {
            return !object.Equals(id1, id2);
        }

        /// <summary>
        /// Serializes the specified writer.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public void Serialize(ISlimBinaryWriter writer)
        {
            writer.WriteInt32(_id);
        }
    }
}
